﻿using AutoMapper;
using HDS.Admin.Api.ViewModels.User;
using HDS.IService.Sys;
using HDS.Model;
using HDS.Model.Entity.Sys;
using LinqKit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;

namespace HDS.Admin.Api.Controllers
{
    [Route("sysuser/[action]")]
    [ApiController]
    [EnableCors]
    [Authorize]
    public class SysUserController : AdminController
    {
        private readonly ILogger<SysUserController> _logger;
        private readonly IMapper _imapper;
        private readonly ISysUserService _isysUserService;
        private readonly ISysRoleService _isysRoleService;
        private readonly ISysFunService _isysFunService;

        public SysUserController(ILogger<SysUserController> logger, IMapper imapper, ISysUserService isysUserService, ISysRoleService isysRoleService, ISysFunService isysFunService)
        {
            _logger = logger;
            _imapper = imapper;
            _isysUserService = isysUserService;
            _isysRoleService = isysRoleService;
            _isysFunService = isysFunService;
        }

        #region User

        [HttpPost]
        public async Task<ResultData<DataPagingModel<SysUserDto>>> GetUserList([FromBody] UserSearchDto userSearchDto)
        {
            var predicate = PredicateBuilder.New<SysUser>(true);
            if (!string.IsNullOrEmpty(userSearchDto.Email))
                predicate = predicate.And(e => e.UserEmail.Contains(userSearchDto.Email));
            if (!string.IsNullOrEmpty(userSearchDto.Name))
                predicate = predicate.And(e => e.UserName.Contains(userSearchDto.Name));
            
            var dataPaging = await _isysUserService.GetList(predicate, userSearchDto.PageIndex, userSearchDto.PageSize);
            var dataPagingView = dataPaging.CopyPageData<SysUserDto>();
            dataPagingView.Rows = _imapper.Map<List<SysUserDto>>(dataPaging.Rows);
            dataPagingView.Rows.ForEach(async item =>
            {
                item.Roles = await _isysUserService.GetRoles(item.UserId);
            });

            return new ResultData<DataPagingModel<SysUserDto>> { Success = true, Data = dataPagingView };
        }

        [HttpPost]
        public async Task<ResultData<string>> SaveUser([FromBody] SaveUserRoleDto dto)
        {
            var entity = _imapper.Map<SysUser>(dto);
            if (entity.UserId > 0)
            {
                await _isysUserService.Update(entity);
                if (!string.IsNullOrEmpty(entity.UserPwd))
                    await _isysUserService.UpdatePwd(entity.UserId, entity.UserPwd);
            }
            else
            {
                var resultData = await _isysUserService.Register(entity);
                if (resultData.Success)
                {
                    entity.UserId = resultData.Data.UserId;
                }
                else
                {
                    return new ResultData<string> { Success = false, Code = resultData.Code, Message = resultData.Message, Data = "" };
                }
            }

            await _isysUserService.SetRoles(entity.UserId, dto.Roles);

            return new ResultData<string> { Success = true };
        }

        [HttpPost]
        public async Task<ResultData<string>> SaveMyInfo([FromBody] SaveUserRoleDto dto)
        {
            await _isysUserService.Update(new SysUser { UserId = this.UserId, UserName = dto.UserName, UserPhone = dto.UserPhone, UserStatus = true });

            return new ResultData<string> { Success = true };
        }

        [HttpPost]
        public async Task<ResultData<string>> SaveMyPwd([FromBody] SaveMyPwdDto dto)
        {
            if (dto.NewPwd1 != dto.NewPwd2)
                return new ResultData<string> { Success = false, Code = ErrorCode.DataValidationFailed, Message = "confirm_password_not_same" };

            var user = await _isysUserService.Get(this.UserId, dto.OldPwd);
            if (user == null)
                return new ResultData<string> { Success = false, Code = ErrorCode.DataValidationFailed, Message = "original_password_error" };

            await _isysUserService.UpdatePwd(this.UserId, dto.NewPwd1);

            return new ResultData<string> { Success = true };
        }

        #endregion

        #region Role

        public async Task<ResultData<List<SysRole>>> GetRoleList()
        {
            var roleList = await _isysRoleService.GetList();
            return new ResultData<List<SysRole>> { Success = true, Data = roleList };
        }

        public async Task<ResultData<string>> SaveRole([FromBody] SysRole entity)
        {
            await _isysRoleService.Save(entity);
            return new ResultData<string> { Success = true };
        }

        public async Task<ResultData<int[]>> GetRoleFuns(int roleId)
        {
            var rolefuns = await _isysRoleService.GetFuns(roleId);
            var role = await _isysRoleService.Get(roleId);

            return new ResultData<int[]> { Success = true, Message = role.RoleName, Data = rolefuns.Select(e => e.FunId).ToArray() };
        }

        public async Task<ResultData<string>> SaveRoleFuns([FromBody] SysRoleFunsDto entity)
        {
            await _isysRoleService.SetFuns(entity.RoleId, entity.FunIds);
            return new ResultData<string> { Success = true };
        }

        #endregion

        #region Fun

        public async Task<ResultData<SysFun>> GetFun(int funId)
        {
            var fun = await _isysFunService.Get(funId);
            if (fun.FunPid > 0)
            {
                var pfun = await _isysFunService.Get(fun.FunPid);
                if (pfun != null)
                    fun.FunPName = pfun.FunName;
            }

            return new ResultData<SysFun> { Success = true, Data = fun };
        }

        public async Task<ResultData<string>> SaveFun([FromBody] SysFun entity)
        {
            await _isysFunService.Save(entity);
            return new ResultData<string> { Success = true };
        }

        public async Task<ResultData<string>> DelFun(int funId)
        {
            await _isysFunService.Delete(funId);
            return new ResultData<string> { Success = true };
        }

        public async Task<ResultData<List<SysFunTreeDto>>> GetFunList()
        {
            var allFunList = await _isysFunService.GetList();
            var allFunTreeList = _imapper.Map<List<SysFunTreeDto>>(allFunList);
            var result = new List<SysFunTreeDto>();
            foreach (var fun0 in allFunTreeList.Where(e => e.FunPid == 0))
            {
                result.Add(GetSysFunChildren(allFunTreeList, fun0));
            }

            return new ResultData<List<SysFunTreeDto>> { Success = true, Data = result };
        }

        private SysFunTreeDto GetSysFunChildren(List<SysFunTreeDto> allFunTreeList, SysFunTreeDto pFun)
        {
            var children = allFunTreeList.Where(e => e.FunPid == pFun.FunId).ToList();
            if (children.Any())
            {
                if (pFun.Children == null)
                    pFun.Children = new List<SysFunTreeDto>();

                pFun.Children.AddRange(children);
                foreach (var child in children)
                {
                    GetSysFunChildren(allFunTreeList, child);
                }
            }

            return pFun;
        }


        #endregion
    }
}
